package com.lsh.oms.core.service.order;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.base.common.json.JsonUtils;
import com.lsh.base.common.model.CommonResult;
import com.lsh.oms.api.model.es.OrderHeadForEs;
import com.lsh.oms.api.model.order.delivery.OrderSendDetailDTO;
import com.lsh.oms.api.model.order.delivery.OrderSendHeadDTO;
import com.lsh.oms.api.model.order.delivery.OrderSendUpdateHeadDTO;
import com.lsh.oms.api.service.es.EsAsyncInterface;
import com.lsh.oms.core.constant.ReturnCode;
import com.lsh.oms.core.enums.OrderStatus;
import com.lsh.oms.core.exception.BusinessException;
import com.lsh.oms.core.model.calService.CalResultVo;
import com.lsh.oms.core.model.calService.CalShippingDetailVo;
import com.lsh.oms.core.model.order.*;
import com.lsh.oms.core.proxy.service.EsProxy;
import com.lsh.oms.core.service.other.ShippingOrderService;
import com.lsh.oms.core.service.payment.OrderSignForRefundService;
import com.lsh.oms.core.utils.ComputeServiceUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Project Name: lsh-oms
 *
 * @author peter
 * @date 18/6/23
 * 北京链商电子商务有限公司
 * Package
 * desc:
 */
@Service
@Slf4j
public class OrderDeliveryService {

    @Autowired
    private ShippingOrderService shippingService;

    @Autowired
    private EsProxy esProxy;


    @Autowired
    private EsAsyncInterface esAsyncInterface;

    @Autowired
    private OrderCancelService orderCancelService;

    @Value("${shopUrl}")
    private String shopUrl;

    @Value("${calUrl}")
    private String calUrl;

    @Autowired
    private OrderSignForRefundService orderSignForRefundService;

    /**
     * 发货单
     *
     * @param orderSendHeadDTO 请求信息
     * @param orderHead        订单信息
     * @param logSign          唯一标识
     * @return 返回值
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public CommonResult<Object> create(OrderSendHeadDTO orderSendHeadDTO, OrderHead orderHead, String logSign, Long venderId) {
        log.info(logSign + " 发货单请求发货参数 " + JsonUtils.obj2Json(orderSendHeadDTO));
        CommonResult<Object> res = new CommonResult<>();
        Map<String, BigDecimal> itemCodeMap = new HashMap<>((int) (orderSendHeadDTO.getItems().size() / (0.75)) + 1);
        Map<Long, OrderSendDetailDTO> itemMap = new HashMap<>((int) (orderSendHeadDTO.getItems().size() / (0.75)) + 1);
        // 判断是否全单捡缺
        BigDecimal orderQty = BigDecimal.ZERO;
        for (OrderSendDetailDTO detail : orderSendHeadDTO.getItems()) {
            if (detail == null || StringUtils.isBlank(detail.getCode()) || detail.getQty() == null) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "明细中有没有物美码或者没有数量，请核实");
            }
            if (detail.getQty().compareTo(BigDecimal.ZERO) <= 0) {
                continue;
            }
            String itemKey = detail.getItem_id() + ":" + detail.getCode();
            BigDecimal qty = itemCodeMap.get(itemKey);
            if (qty == null) {
                itemCodeMap.put(itemKey, detail.getQty());
            } else {
                itemCodeMap.put(itemKey, detail.getQty().add(qty));
            }
            orderQty = orderQty.add(detail.getQty());

            itemMap.put(detail.getItem_id(), detail);
        }

        if (orderQty.compareTo(BigDecimal.ZERO) == 0) {
            CommonResult commonResult = null;
            try {
                commonResult = orderCancelService.orderAllPickUpShortCancel(orderSendHeadDTO, "oms-cancel-order", venderId);
            } catch (Exception e) {
                log.error("订单取消失败", e);
            }
            log.info("{} 订单全单捡缺, 处理结果:{}", logSign, JSON.toJSONString(commonResult));
            if (CommonResult.SUCCESS.equals(commonResult.getCode())) {
                res.setCode(ReturnCode.REQUEST_SUCCESS);
                res.setMessage("订单全单捡缺");

                this.notifyMis(orderHead);

            } else {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "订单全单捡缺,取消订单失败");
            }
            return res;
        }
        Long orderCode = orderHead.getOrderCode();
        //请求计算服务
        CalResultVo calResultVo = this.requestCal(orderSendHeadDTO, itemCodeMap, logSign, orderHead.getVenderId());
        OrderShippingHeadWithBLOBs orderShippingHead = OrderFactory.createShippingHead(orderSendHeadDTO, orderHead, calResultVo);
        List<OrderShippingDetail> orderShippingDetails = this.getOrderShippingDetails(orderShippingHead, calResultVo, itemMap, orderHead);
        boolean successFlag;
        OrderStatus orderStatus = OrderStatus.ORDER_SORTING;
        Integer sale_model = orderSendHeadDTO.getSale_model();
        Integer delivery_type = orderSendHeadDTO.getDelivery_type();
        if(null != delivery_type && delivery_type == 4){
            orderStatus = OrderStatus.ORDER_DELIVERY;
        }

        try {
            successFlag = this.shippingService.dealShipping(orderShippingHead, orderShippingDetails, orderStatus, logSign);
        } catch (Throwable e) {
            log.info(logSign + "发货单保存数据库失败，订单号:" + orderCode);
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "发货单保存数据库失败");
        }
        //通知es
        log.info(orderCode + " 发货单持久化 successFlag = " + successFlag);
        if (successFlag) {
            this.notifyEsOrderInfo(orderCode, OrderFactory.getMarketName(orderHead), OrderFactory.getProviderId(orderHead), orderStatus, logSign);
        }
        Map<String, Object> respMap = new HashMap<>(6);
        respMap.put("flag", successFlag);
        if (successFlag) {
            res.setCode(ReturnCode.REQUEST_SUCCESS);
        } else {
            res.setCode(ReturnCode.REQUEST_FAIL);
        }
        res.setData(respMap);
        return res;

    }

    private void notifyMis(OrderHead orderHead){

        try {
            orderSignForRefundService.orderFinishForCoupon(orderHead.getOrderCode());
            orderSignForRefundService.orderCancelForRefund(orderHead.getOrderCode());
        }catch (Exception e){
            log.info("订单签单拣缺取消通知mistask 添加失败");
        }
    }


    /**
     * 请求计算服务
     *
     * @param orderSendHeadDTO 发货信息
     * @param logSign          唯一标识
     * @return 计算结果
     */
    private CalResultVo requestCal(OrderSendHeadDTO orderSendHeadDTO, Map<String, BigDecimal> itemMap, String logSign, Long venderId) {

        CalResultVo calVo = ComputeServiceUtils.requsetCalService4obd(orderSendHeadDTO, itemMap, logSign, calUrl, venderId);
        log.info(logSign + "请求计算服务返回信息" + JsonUtils.obj2Json(calVo));
        if (calVo == null || calVo.getHead() == null || calVo.getDetail() == null || calVo.getDetail().size() == 0) {
            log.info(logSign + ",计算服务获取信息为空,订单号:" + orderSendHeadDTO.getOrder_id());
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "计算服务获取信息为空");
        }

        return calVo;
    }

    /**
     * 组织签收单详情列表
     *
     * @param osh   签收单详情
     * @param calVo 计算服务数据
     * @return 返回数据
     */
    private List<OrderShippingDetail> getOrderShippingDetails(OrderShippingHeadWithBLOBs osh, CalResultVo calVo, Map<Long, OrderSendDetailDTO> itemMap, OrderHead orderHead) {
        List<CalShippingDetailVo> detailVoList = calVo.getDetail();
        List<OrderShippingDetail> details = new ArrayList<>(detailVoList.size());
        int sysTime = (int) TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
        Integer lackFlag = 0;

        Map<Integer, OrderDetail> orderDetailMap = orderHead.getDetails().stream().collect(Collectors.toMap(OrderDetail::getItemCode, orderDetail -> orderDetail));

        //检查无效数据
        boolean filterFlag = detailVoList.stream().anyMatch(calShippingDetailVo -> {
            Integer itemCode = calShippingDetailVo.getItemCode();
            JSONObject jsonObject = JSON.parseObject(calShippingDetailVo.getExt());
            String wgCode = jsonObject.getString("wm_code");

            return StringUtils.isBlank(wgCode) || null == itemCode || itemCode == 0;
        });

        if (filterFlag) {
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "请求信息与计算服务参数不符 filter check");
        }

        for (CalShippingDetailVo detailVo : detailVoList) {
            OrderShippingDetail detail = new OrderShippingDetail(detailVo);

            JSONObject jsonObject = JSON.parseObject(detailVo.getExt());
            String wgCode = jsonObject.getString("wm_code");
            OrderSendDetailDTO detailDTO = itemMap.get(detailVo.getItemId());

            detail.setShippingOrderId(osh.getShippingOrderId());
            detail.setZoneId(osh.getZoneId());
            detail.setVenderId(osh.getVenderId());
            // TODO 2019-12-24 peter
            detail.setSupplierOrg(Integer.parseInt(detailDTO.getSupplier_org()));
            detail.setCode(wgCode);
            detail.setItemId(detailVo.getItemId());
            detail.setCreatedAt(sysTime);
            detail.setUpdatedAt(sysTime);
            detail.setQty(new BigDecimal(detailVo.getQty()));
            detail.setItemCode(detailVo.getItemCode());
            Integer weightFlag = detailVo.getIsWeighingGoods();
            jsonObject.put("is_weighing_goods", weightFlag == null ? 0 : weightFlag);
            jsonObject.put("obd_detail_ext", detailDTO.getObd_detail_ext());
            detail.setExt(jsonObject.toJSONString());

            details.add(detail);

            OrderDetail orderDetail = orderDetailMap.get(detailVo.getItemCode());
            BigDecimal orderDetailRealQty = JSONObject.parseObject(orderDetail.getDetailExt()).getBigDecimal("realQty");
            if ((orderDetailRealQty.subtract(detail.getRealQty())).compareTo(BigDecimal.ONE) >= 0) {
                lackFlag = 1;
            }
        }

        osh.setLackFlag(lackFlag);

        return details;
    }


    /**
     * 通知ES
     *
     * @param orderCode 订单号
     * @param logSign   唯一标识
     */
    private void notifyEsOrderInfo(Long orderCode, String marketName, String providerId, OrderStatus orderStatus, String logSign) {
        try {
            OrderShippingHeadWithBLOBs shippingEs = shippingService.getBolbs(orderCode);

            log.info(logSign + "pms-ES入参新建发货索引参数是:" + JsonUtils.obj2Json(shippingEs));
            shippingEs.setMarketName(marketName);
            shippingEs.setProviderId(providerId);
            String addressInfo = shippingEs.getAddressInfo();
//            String omsExt = shippingEs.getOmsExt();
            if (StringUtils.isNotBlank(addressInfo)) {
                JSONObject address = JSON.parseObject(addressInfo);
                shippingEs.setAddressTelephone(address.getString("contact_phone"));
            }
            log.info(logSign + "pms-ES入参新建发货索引参数all是:" + JsonUtils.obj2Json(shippingEs));
            esProxy.createIndex(shippingEs, logSign);
            OrderHeadForEs ohEs = new OrderHeadForEs();
            ohEs.setOrderCode(orderCode);
            ohEs.setOrderStatus(orderStatus.getIndex());
            ohEs.setLackDeliveryType(shippingEs.getLackFlag());
            log.info(logSign + "pms-ES入参发货单是:" + JsonUtils.obj2Json(ohEs));
            esProxy.editIndex(ohEs, logSign);
        } catch (Exception e) {
            log.info(logSign + "订单号" + orderCode + ",生成发货单同步es失败。");
            log.info(e.getMessage(), e);
        }
    }


    @Transactional
    public boolean updateDriverInfo2ext(OrderSendUpdateHeadDTO orderSendUpdateHeadDTO) {
        OrderShippingHead orderShippingHead = shippingService.selectOneByOrderCode(orderSendUpdateHeadDTO.getOrderCode(), false);

        if (orderShippingHead == null) {
            log.info(orderSendUpdateHeadDTO.getOrderCode() + " -> 发货单信息不存在");
            return false;
        }

        JSONObject omsExtJson;
        if (StringUtils.isBlank(orderShippingHead.getOmsExt())) {
            omsExtJson = new JSONObject();
        } else {
            omsExtJson = JSON.parseObject(orderShippingHead.getOmsExt());
        }

        if (omsExtJson == null) {
            log.info(orderSendUpdateHeadDTO.getOrderCode() + " -> omsExtJson 初始化失败");
            return false;
        }

        String deliveryInfo = orderSendUpdateHeadDTO.getDeliveryInfo();

        if (StringUtils.isBlank(deliveryInfo)) {
            return false;
        }
        JSONObject deliveryJson = JSON.parseObject(deliveryInfo);

        omsExtJson.put("deliveryInfo", deliveryJson);

        OrderShippingHead record = new OrderShippingHead();
        record.setShippingOrderId(orderShippingHead.getShippingOrderId());
        record.setOmsExt(omsExtJson.toJSONString());
        int time = (int) TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
        record.setUpdatedAt(time);

        if (shippingService.updateOmsExtByShippingId(record) > 0) {
//            this.updateEs(orderShippingHead.getShippingOrderId(), deliveryJson);
        } else {
            return false;
        }

        return true;
    }

    public void dealEs(OrderHead orderHead){

        OrderHeadForEs es = EsProxy.transformToOrderHeadForEs(orderHead, true);
        log.info("order ES data is " + JSON.toJSONString(es));
        esAsyncInterface.editIndex(es);
    }

    public void dealsEs(OrderShippingHeadWithBLOBs shippingEs){

        log.info("ship ES data is " + shippingEs.getShippingOrderId());
        esAsyncInterface.createIndex(shippingEs);
    }

    public void dealrEs(OrderSignHead orderSignHead){

        log.info("sign ES data is " + orderSignHead.getReceiptOrderId());
        esAsyncInterface.createIndex(orderSignHead);
    }

//    private void updateEs(Long shippingOrderId, JSONObject deliveryJson) {
//
//        OrderShippingHeadWithBLOBs oshEs = new OrderShippingHeadWithBLOBs();
//        oshEs.setShippingOrderId(shippingOrderId);
//        oshEs.setDeliveryUserId(deliveryJson.getString("employeeId"));
//        oshEs.setDeliveryUserName(deliveryJson.getString("deliveryName"));
//        oshEs.setDeliveryUserPhone(deliveryJson.getString("deliveryPhone"));
//
//        log.info(shippingOrderId + "ES入参修改发货是-- " + JsonUtils.obj2Json(oshEs));
//        esProxy.editIndex(oshEs, shippingOrderId + "");
//    }

}



